﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CodeGenerationPipeline.Contracts;
using System.Diagnostics;
using System.IO;
using AbstraX.Contracts;
using Microsoft.Build.Framework;

namespace CodeGenerationPipeline
{
    public abstract class BaseGenerator : IGenerator
    {
        public Exception LastException { get; protected set; }
        public abstract event OnFileGeneratedHandler OnFileGenerated;
        protected IPipelineTemplateEngineHost templateEngineHost;
        protected IDomainHostApplication domainHost;
        protected string sDKFolder;
        protected string dotNetFxFolder;
        protected string workspaceDirectory;
        protected IPipelineStep pipelineStep;
        protected Dictionary<string, FileInfo> files;
        private EventSourceDispatcher eventSourceDispatcher;
        public IEventsService EventsService { get; set; }
        public abstract event WatchProcess OnWatchProcess;
        public abstract string Name { get; }
        public abstract string Description { get; }
        public abstract IProgrammingLanguage ProgrammingLanguage { get; }
        public abstract ICodeGenerationPackage GenerateFrom(Dictionary<string, IElementBuild> builds, DirectoryInfo workspaceDirectory);
        public abstract ICodeGenerationPackage GenerateFromPackage(ICodeGenerationPackage incomingPackage);

        public IDomainHostApplication DomainHostApplication
        {
            set
            {
                domainHost = value;

                eventSourceDispatcher = new EventSourceDispatcher(domainHost.EventsService, this.Name);
            }

            get
            {
                return domainHost;
            }
        }

        public IList<IEventSource> EventSources
        {
            get
            {
                return eventSourceDispatcher;
            }
        }

        public IPipelineTemplateEngineHost TemplateEngineHost
        {
            set
            {
                templateEngineHost = value;
            }

            get
            {
                return templateEngineHost;
            }
        }

        public IPipelineStep PipelineStep
        {
            set 
            {
                pipelineStep = value;
            }
        }

        public virtual void OnError(int errorCode, Exception exception, string error)
        {
        }

        public virtual void OnProcessExited(int exitCode)
        {
        }

        public virtual void OnOutput(string output)
        {
        }

        public virtual void OnProcessTimeout()
        {
            Debugger.Break();
        }

        public string SDKFolder
        {
            set
            {
                sDKFolder = value;
            }

            get
            {
                return sDKFolder;
            }
        }

        public string DotNetFxFolder
        {
            set
            {
                dotNetFxFolder = value;
            }

            get
            {
                return dotNetFxFolder;
            }
        }

        public string WorkspaceDirectory
        {
            get
            {
                return workspaceDirectory;
            }
        }

        public virtual void OnFileCreated(FileInfo file)
        {
            this.Files.Add(file.FullName, file);
        }

        public virtual void OnFileChanged(FileInfo file)
        {
        }

        public virtual void OnFileRenamed(FileInfo file, FileInfo oldFile)
        {
            if (this.Files.ContainsKey(oldFile.FullName))
            {
                this.Files.Remove(oldFile.FullName);
            }

            this.Files.Add(file.FullName, file);
        }

        public virtual void OnFileDeleted(FileInfo file)
        {
            if (this.Files.ContainsKey(file.FullName))
            {
                this.Files.Remove(file.FullName);
            }
        }

        public Dictionary<string, FileInfo> Files
        {
            get 
            {
                if (files == null)
                {
                    files = new Dictionary<string, FileInfo>();
                }

                return files;
            }
        }
    }
}
